package cn.chenxing.module.file.controller;

import cn.chenxing.domain.dto.TrackData;
import cn.chenxing.domain.dto.TrackLine;
import cn.chenxing.domain.dto.TrackPoint;
import cn.chenxing.domain.threadlocal.ThreadData;
import cn.chenxing.domain.util.AlertUtil;
import cn.chenxing.domain.util.DateUtil;
import cn.chenxing.domain.util.DialogBuilderUtil;
import cn.chenxing.domain.util.FileChooserUtil;
import cn.chenxing.module.file.service.FileService;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXCheckBox;
import com.jfoenix.controls.JFXComboBox;
import de.felixroske.jfxsupport.FXMLController;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextField;
import javafx.scene.control.TitledPane;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Description
 * @Author maogen.ymg
 * @Date 2020/4/10 23:19
 */
@Lazy
@FXMLController
@Slf4j
public class FileStructAnalysisController implements Initializable {

    private File tableFile;

    @FXML
    private TextField filePath;

    @FXML
    private JFXButton chooseFile;

    @FXML
    private TextField separator;

    @FXML
    private TitledPane titlePane;

    @FXML
    private JFXCheckBox firstLine;

    @FXML
    private JFXComboBox longitudeX;

    @FXML
    private JFXComboBox latitudeY;

    @FXML
    private JFXComboBox<String> coordinateUnit;

    @FXML
    private JFXComboBox time;

    @FXML
    private JFXComboBox<String> timeFormat;

    @FXML
    private JFXCheckBox isSpeed;

    @FXML
    private JFXComboBox speed;

    @FXML
    private JFXComboBox idField;

    @FXML
    private JFXButton execute;

    @FXML
    private JFXButton close;

    @Autowired
    private FileService fileService;

    @SuppressWarnings("unchecked")
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // 坐标单位
        coordinateUnit.getItems().addAll("度");
        coordinateUnit.setValue(coordinateUnit.getItems().get(0));
        // 时间格式
        timeFormat.getItems().addAll("yyyy-MM-dd HH:mm:ss");
        timeFormat.setValue(timeFormat.getItems().get(0));
        // 选择文件
        Image btnImg = new Image("/images/main/file/choose.png");
        chooseFile.setGraphic(new ImageView(btnImg));

        // 面板初始化不可用
        titlePane.setDisable(true);
        // 速度字段复选框监听
        speed.setDisable(true);
        isSpeed.setSelected(false);
        isSpeed.selectedProperty().addListener((ov, oldValue, newValue) -> speed.setDisable(!newValue));
    }

    @SuppressWarnings("unchecked")
    @FXML
    private void chooseFile() {
        tableFile = FileChooserUtil.chooseTableFile("请选择本地文件");
        if(tableFile.exists() && tableFile.isFile()){
            filePath.setText(tableFile.getName());
            // 弹框获取分隔符
            final boolean[] isCancel = {false};
            new DialogBuilderUtil(chooseFile)
                    .setTitle("分隔符")
                    .setMessage("请输入文本分隔符（字符）")
                    .setTextFieldText(result -> separator.setText(result.trim()))
                    .setPositiveBtn("确定")
                    .setNegativeBtn("取消", () -> isCancel[0] = true).create();
            if(isCancel[0]) {
                separator.setText("");
                return;
            }
            // 字段
            List<String> fieldList = new ArrayList<>();
            try(InputStreamReader inputReader = new InputStreamReader(new FileInputStream(tableFile));
                BufferedReader bReader = new BufferedReader(inputReader)) {

                // 排除首行为字段描述信息
                String str = bReader.readLine();

                if((str = bReader.readLine())!=null) {
                    String[] strGps = str.split(separator.getText().trim());
                    for(int i = 1; i < strGps.length +1; i++) {
                        fieldList.add("字段" + i);
                    }
                }
            } catch (Exception e) {
                AlertUtil.showErrorAlert("文件读取错误", "数据读取失败，请检查格式是否符合要求！");
            }
            if(fieldList.size() < 4) {
                AlertUtil.showErrorAlert("文件读取错误", "分隔符选择错误，请重新导入数据");
            }
            // 面板可用
            titlePane.setDisable(false);
            // 清空并添加下拉框内容
            idField.getItems().clear();
            idField.getItems().addAll(fieldList);
            idField.setValue(fieldList.get(0));
            time.getItems().clear();
            time.getItems().addAll(fieldList);
            time.setValue(fieldList.get(1));
            longitudeX.getItems().clear();
            longitudeX.getItems().addAll(fieldList);
            longitudeX.setValue(fieldList.get(2));
            latitudeY.getItems().clear();
            latitudeY.getItems().addAll(fieldList);
            latitudeY.setValue(fieldList.get(3));
            speed.getItems().clear();
            speed.getItems().addAll(fieldList);
            speed.setValue(fieldList.get(0));

        }
    }

    @FXML
    private void execute() {
        if(StringUtils.isBlank(filePath.getText())) {
            DialogBuilderUtil.showPositiveAlert(execute,"提示", "未选择文件数据");
            return;
        }

        String str;
        // 点ID
        int id = 0;
        // 用户ID
        int userId = -1;
        // 是否是第一个ID
        boolean isFirstId = true;
        // 首行是否被选中
        boolean isSelFirstLine = firstLine.isSelected();

        List<TrackPoint> primeCoordinate = new ArrayList<>();
        List<TrackLine> trackLineList = new ArrayList<>();

        // 文件中ID数据
        int idValue = 0;
        try(InputStreamReader inputReader = new InputStreamReader(new FileInputStream(tableFile));
            BufferedReader bReader = new BufferedReader(inputReader)) {

            while((str = bReader.readLine())!=null){
                // 首行
                if(isSelFirstLine) {
                    isSelFirstLine = false;
                    continue;
                }
                String[] strGps = str.split(separator.getText().trim());
                // ID
                idValue = Integer.parseInt(strGps[getNumbers(idField.getValue().toString())-1]);
                // 经度
                double longitude = Double.parseDouble(strGps[getNumbers(longitudeX.getValue().toString())-1]);
                // 纬度
                double latitude = Double.parseDouble(strGps[getNumbers(latitudeY.getValue().toString())-1]);
                // 时间戳转换
                long timeStamp = DateUtil.date2TimeStamp(strGps[getNumbers(time.getValue().toString())-1], null);

                // 过滤掉重复相同点--经纬度时间一致
                if(fileService.isSamePoint(longitude, latitude, timeStamp)) {
                    continue;
                }

                TrackPoint point = new TrackPoint();
                point.setId(id++);
                point.setLongitude(longitude);
                point.setLatitude(latitude);
                point.setTimeStamp(timeStamp);
                // 速度字段
                if(isSpeed.isSelected()) {
                    double speedField = Double.parseDouble(strGps[getNumbers(speed.getValue().toString())-1]);
                    point.setSpeed(speedField);
                }
                // 第一个ID获取赋值给userId
                if(isFirstId) {
                    userId = idValue;
                    isFirstId = false;
                }

                if(idValue != userId) {
                    // List间赋值，而不是引用
                    List<TrackPoint> tempPointList = new ArrayList<>(primeCoordinate);
                    TrackLine trackLine = new TrackLine();
                    trackLine.setId(userId);
                    trackLine.setTrackPointList(tempPointList);
                    trackLineList.add(trackLine);
                    // 清空 为下一次服务
                    primeCoordinate.clear();
                    id = 0;
                    userId = idValue;
                }else {
                    primeCoordinate.add(point);
                }

            }// while

            TrackLine trackLine = new TrackLine();
            trackLine.setId(idValue);
            trackLine.setTrackPointList(primeCoordinate);
            trackLineList.add(trackLine);

        }catch (Exception e) {
            log.error("文件读取分析错误，原因为{}", e.getLocalizedMessage(),e);
            AlertUtil.showErrorAlert("分析错误", "文件分析错误，请检查填写内容是否有误");
        }

        // 文件所有轨迹数据
        TrackData trackData = new TrackData();
        trackData.setTrackLineList(trackLineList);
        // 传值给ThreadData
        ThreadData.get().setFileUrl(tableFile.getAbsolutePath());
        ThreadData.get().setHasSpeed(isSpeed.isSelected());
        ThreadData.get().setTrackData(trackData);

        // 成功后关闭
        close();
    }

    @FXML
    private void close() {
        Stage stageWindow = (Stage) close.getScene().getWindow();
        // 面板初始化不可用
        titlePane.setDisable(true);
        // 速度字段复选框监听
        speed.setDisable(true);
        isSpeed.setSelected(false);
        // 文件路径清空
        filePath.setText("");
        stageWindow.close();
    }

    /**
     * 从字符串中获取数字
      * @param content 文本
     * @return 数字
     */
    private int getNumbers(String content) {
        String regEx = "[^0-9]";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(content);
        String str = m.replaceAll("").trim();
        if(StringUtils.isNoneBlank(str)) {
            return Integer.parseInt(str);
        }
        AlertUtil.showErrorAlert("分析结构失败", "字段值为空，请检查并重试！");
        // unused
        return 0;
    }

}
